package wsi.gui.resolve;

import javafx.scene.control.Tooltip;
import javafx.scene.text.Text;

import org.rygh.gui.comp.Label;
import org.rygh.gui.comp.Table;
import org.rygh.gui.comp.TextArea;
import org.rygh.gui.comp.xml.XmlTreeView;
import org.rygh.gui.model.Presenter;
import org.rygh.gui.view.one.OneEditorView;
import org.rygh.gui.view.one.OneXmlView;
import org.rygh.gui.window.Window;

import wsi.gui.resolve.model.JudgeItem;
import wsi.gui.resolve.model.JudgeItemIterator;
import wsi.gui.resolve.model.MatchInfoData;
import wsi.gui.resolve.model.MatchInfoTuple;
import wsi.match.MatchProperty;

public class JudgePresenter extends Presenter {

	public interface Display extends Presenter.Display {

	}

	private final JudgeItemIterator iterator = new JudgeItemIterator();
	private final Window xmlWindow;
	private final Window noteWindow;

	private boolean judgeAll = true;
	private JudgeItem item = null;

	public JudgePresenter() {
		String title = "Human-Assisted Judgment";
		display = new Window(title, new JudgeView(this), 1000, 500);
		xmlWindow = new Window("Xml View", new OneXmlView(this), 800, 500);
		noteWindow = new Window("Note", new OneEditorView(this), 320, 320);

		getNoteTextArea().setFontMono();
	}

	private boolean checkEmpty() {
		if (item == null) {
			getWindow().tooltip(getDownLabel(), "null");
			return false;
		}

		if (item.isEmpty()) {
			getWindow().tooltip(getDownLabel(), "Empty match.");
			return false;
		}

		return true;
	}

	private void clear() {
		item = null;

		getTable().clear();
		getTable().setPlaceholder(new Text("Completed!"));

		getUpLabel().clear();
		getDownLabel().clear();
	}

	public void compute() {
		if (!checkEmpty())
			return;

		getNoteTextArea().setText(item.getComputeProbString());

		noteWindow.display();
	}

	public void correct() {
		if (!checkEmpty())
			return;

		item.setResult(true);
		next();
	}

	private Label getDownLabel() {
		return invoke("display.view.bottomView.downLabel");
	}

	public TextArea getNoteTextArea() {
		return invoke("noteWindow.view.textArea");
	}

	public Window getNoteWindow() {
		return noteWindow;
	}

	private Table<MatchInfoTuple> getTable() {
		return invoke("display.view.tableView.table");
	}

	private Label getUpLabel() {
		return invoke("display.view.bottomView.upLabel");
	}

	private XmlTreeView getXmlTree() {
		return invoke("xmlWindow.view.tree");
	}

	public Window getXmlWindow() {
		return xmlWindow;
	}

	public void judge(JudgeItem item) {
		this.item = item;
		judgeAll = false;

		item.setIterateAll(true);
		item.resetIndex();
		next();
	}

	public void judgeAll() {
		judgeAll = true;
		item = null;
		next();
	}

	private void load() {
		// System.out.printf("[info] load at %d\n", item.getIndex());

		resetTable();

		if (item.isEmpty()) {
			getDownLabel().setText(
					"Empty: " + item.getFunction().getFullName() + ", "
							+ item.getFile().getName());
		} else {
			MatchInfoData data = item.get();
			getTable().setData(data);

			Boolean judge = item.getJudgment();

			getDownLabel().setText(
					String.format("%s > (%.2f, %s) %s", item.getSubrootPath()
							.stripIndex(), data.getProbability(),
							judge == null ? "null" : judge, data.getEntity()
									.getValue()));

			getDownLabel().setTooltip(new Tooltip(item.getFile().getName()));
		}

		//

		MatchProperty mp = item.getMatchProperty();
		String match_prop = "";

		if (mp.isExistsMatch())
			match_prop = Integer.toString(mp.getSubtreeIndex());
		else
			match_prop = mp.getPredicatePath().getKey();

		getUpLabel().setText(
				String.format("%s: %s (%s), %d / %d items.", item.getFunction()
						.getFullName(), mp.getType().name(), match_prop, item
						.getIndex(), item.size()));

		item.moveIndex();

		// put them after moving index, because when the user clicks, it's after

		if (!item.isEmpty()) {
			if (xmlWindow.isShown())
				view();

			if (noteWindow.isShown())
				compute();
		}

	}

	public void next() {
		// if (item != null)
		// System.out.printf("[info] item %d / %d\n", item.getIndex(),
		// item.size());

		if (item == null || item.isEmpty() || item.checkIndex()) {
			// System.out.println("[info] save & retrieve");

			if (item != null)
				item.save();

			if (judgeAll)
				retrieve();
			else
				clear();

			return;
		}

		load();
	}

	private void resetTable() {
		getTable().clear();
		getUpLabel().clear();
		getDownLabel().clear();
	}

	private void retrieve() {
		item = iterator.next();

		if (item == null) {
			getUpLabel().setText("All items are judged.");
			getDownLabel().setText("");
			clear();
			return;
		}

		// System.out.printf("[info] retrieved %s\n", item.size());

		item.resetIndex();
		load();
	}

	@Deprecated
	public void skip() {
		if (item == null)
			return;

		if (!item.isEmpty()) {
			getWindow().tooltip(getDownLabel(), "Non-empty match, must judge.");
			return;
		}

		next();
	}

	public void view() {
		if (!checkEmpty())
			return;

		getXmlTree().load(item.getXmlTree());

		xmlWindow.display();
	}

	public void wrong() {
		if (!checkEmpty())
			return;

		item.setResult(false);
		next();
	}
}
